home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Pascal Super Library
/
Pascal Super Library (CW International)(1997).bin
/
TSR
/
TPPOP18C
/
WINDOWS.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1989-01-22
|
13KB
|
439 lines
{$A+,B-,D+,E+,F-,I+,L+,N+,O-,R-,S-,V-}
Unit Windows;
Interface
Uses Crt;
Const
On = True;
Off = False;
Type
BorderType = (None,Single,Double,DoubleTop,DoubleSide,Solid);
TitleType = (LeftJustify,Centered,RightJustify);
ScreenType = Array[0..3999] of Byte;
ScreenPtr = ^ScreenRecord;
ScreenRecord = Record
Screen : ^ScreenType; { points to saved screen tile }
uX,uY,lX,lY : Byte; { holds new window coordinates }
UpperCors : Word; { holds old window coordinates }
LowerCors : Word; { holds window coordinates }
OldAttr : Word; { holds character attribute }
XY : Word; { holds the cursor position }
Cursor : Word; { holds the cursor shape }
Previous : ScreenPtr; { pointer to underlying window }
End;
Var
UnderScreen : ScreenPtr; { points to the saved screen }
UseMono : Boolean; { true if use B/W attribute only }
TranslateBW : Boolean; { change attributes when mono? }
Procedure Initialize;
Procedure DrawBox(X1,Y1,X2,Y2,Forground,Background : Integer;
Border : BorderType);
Procedure Title(Line : String;TitleFormat : TitleType;Border : BorderType);
Procedure Footer(Line : String;TitleFormat : TitleType;Border : BorderType);
Procedure Cursor(State : Boolean);
{ Turns the cursor on or off. }
Procedure DuplicateChar(Character : Char;Count : Integer);
Procedure DrawVerticalLine(X,Y,Length : Word;Border : BorderType);
Procedure DrawHorizontalLine(X,Y,Length : Word;Border :BorderType);
Procedure SaveScreen(X1,Y1,X2,Y2 : Integer);
Procedure MakeWindow(X1,Y1,X2,Y2,Forground,BackGround : Integer;
Border : BorderType);
Procedure RemoveWindow;
Function VideoMode : Byte;
InLine($B4/$0F/ { mov ah,0Fh }
$CD/$10); { int 10h }
Procedure GotoXYAbs(XY : Word);
InLine($5A/ { pop dx }
$B4/$02/ { mov ah,2 }
$30/$FF/ { xor bh,bh }
$CD/$10); { int 10h }
Function WhereXYAbs : Word;
InLine($B4/$03/ { mov ah,3 }
$30/$FF/ { xor bh,bh }
$CD/$10/ { int 10h }
$89/$D0); { mov ax,dx }
Procedure SetCursor(Cursor : Word);
InLine($59/ { pop cx }
$B4/$01/ { mov ah,1 }
$CD/$10); { int 10h }
Function CursorShape : Word;
InLine($B4/$03/ { mov ah,3 }
$30/$FF/ { xor bh,bh }
$CD/$10/ { int 10h }
$89/$C8); { mov ax,cx }
Type
BorderPart = (Top,Side,UpperLeft,UpperRight,LowerLeft,LowerRight,
TopConnect,BottomConnect,LeftConnect,RightConnect,Cross);
Const
Borders : Array[Single..Solid,Top..Cross] of Char =
(('─','│','┌','┐','└','┘','┬','┴','├','┤','┼'), {single}
('═','║','╔','╗','╚','╝','╦','╩','╠','╣','╬'), {double}
('═','│','╒','╕','╘','╛','╤','╧','╞','╡','╪'), {combo }
('─','║','╓','╖','╙','╜','╥','╨','╟','╢','╫'), {combo }
(' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '));{solid }
{ window type 0 has no border, type 5 uses the space character }
Implementation
Var
MonoScreen : ScreenType Absolute $B000:0000; { monochome screen }
ColorScreen : ScreenType Absolute $B800:0000; { CGA screen }
CurrentScreen : ScreenPtr; { place to save screen info }
ScreenSaved : Boolean; { Are any windows on the heap?}
Procedure Cursor(State : Boolean); External; {$L cursor.obj }
Procedure ScreenToBuffer(Var Source,Target : ScreenType;
X1,Y1,X2,Y2: Integer);
Var
Loop : Word;
Width : Integer;
Offset : Integer;
TIndex : Integer;
SIndex : Integer;
Begin
Offset := Pred(X1) Shl 1;
Width := (X2 - Pred(X1)) Shl 1;
For Loop := Y1 to Y2 Do
Begin
SIndex := Pred(Loop) * 160 + Offset;
TIndex := (Loop-Y1) * Width;
If CheckSnow Then Repeat Until Port[$3DA] AND 1 = 1;
Move(Source[SIndex],Target[TIndex],Width);
End;
End;
Procedure BufferToScreen(Var Source,Target : ScreenType;
X1,Y1,X2,Y2: Integer);
Var
Loop : Word;
Width : Integer;
Offset : Integer;
SIndex : Integer;
TIndex : Integer;
Begin
Offset := Pred(X1) Shl 1;
Width := (X2 - Pred(X1)) Shl 1;
For Loop := Y1 to Y2 Do
Begin
TIndex := Pred(Loop) * 160 + Offset;
SIndex := (Loop-Y1) * Width;
If CheckSnow Then Repeat Until Port[$3DA] AND 9 = 9;
Move(Source[SIndex],Target[TIndex],Width);
End;
End;
Procedure SaveScreen(X1,Y1,X2,Y2 : Integer);
{ saves the screen memory, window coordinates, }
{ cursor position, and character attribute. }
Var
ScreenSize : Integer;
Width : Integer;
Height : Integer;
NewScreen : ScreenPtr;
Begin
Width := Succ(X2) - X1;
Height := Succ(Y2) - Y1;
ScreenSize := (Width * Height) Shl 1;
GetMem(NewScreen,SizeOf(ScreenRecord));
With NewScreen^ Do
Begin
uX := X1;
uY := Y1;
lX := X2;
lY := Y2;
GetMem(Screen,ScreenSize);
If ScreenSaved
Then Previous := CurrentScreen
Else Previous := Nil;
ScreenSaved := True;
If VideoMode = 7
Then ScreenToBuffer(MonoScreen,Screen^,X1,Y1,X2,Y2)
Else ScreenToBuffer(ColorScreen,Screen^,X1,Y1,X2,Y2);
UpperCors := WindMin; { save the window coordinates }
LowerCors := WindMax;
OldAttr := TextAttr; { save the character attribute }
XY := WhereXYAbs; { save the cursor position }
Cursor := CursorShape;
End;
CurrentScreen := NewScreen;
UnderScreen := CurrentScreen;
End;
Procedure DropWindow;
Var
OldScreen : ScreenPtr;
Begin
With CurrentScreen^ Do
Begin
If Previous = Nil Then ScreenSaved := False;
OldScreen := CurrentScreen; { release heap memory }
CurrentScreen := Previous;
UnderScreen := CurrentScreen;
FreeMem(OldScreen,SizeOf(ScreenRecord));
End;
End;
Procedure RemoveWindow;
{ Restores screen memory, window coordinates, }
{ cursor position, and character attribute. }
Var
Height : Integer;
Width : Integer;
ScreenSize : Integer;
Begin
If Not ScreenSaved Then Exit;
With CurrentScreen^ Do
Begin
If VideoMode = 7 Then
BufferToScreen(Screen^,MonoScreen,uX,uY,lX,lY)
Else BufferToScreen(Screen^,ColorScreen,uX,uY,lX,lY);
Width := Succ(lX) - uX;
Height := Succ(lY) - uY;
ScreenSize := (Width * Height) Shl 1;
FreeMem(Screen,ScreenSize);
WindMin := UpperCors; { restore the window coordinates }
WindMax := LowerCors;
TextAttr := OldAttr; { restore the character attribute }
GotoXYAbs(XY); { restore the cursor position }
SetCursor(Cursor);
DropWindow;
End;
End;
Procedure DuplicateChar(Character : Char;Count : Integer);
{ Uses the BIOS to write multiple copies of a character to the screen }
Begin
InLine($8A/$46/<Character/ { mov al,byte ptr char[bp] }
$8B/$4E/<Count/ { mov cx,count[bp] }
$B4/$09/ { mov ah,09h }
$8A/$1E/>TextAttr/ { mov bl,[TextAttr] }
$32/$FF/ { xor bh,bh }
$CD/$10); { int 10h }
End;
Procedure HeaderFooter(Line : String;
Row : Integer;
TitleFormat : TitleType;
Border : BorderType);
Var
WMin,WMax : Word;
oX,oY,X : Integer;
Center : Integer;
Len : Integer;
Begin
WMin := WindMin;
WMax := WindMax;
oX := WhereX;
oY := WhereY;
WindMin := WMin - $0101;
WindMax := WMax + $0101;
Len := Length(Line) Shr 1;
Case TitleFormat Of
LeftJustify : X := 3;
Centered : X := ((Succ(Lo(WindMax)) - Lo(WindMin)) Shr 1) - Len;
RightJustify : X := Lo(WindMax) - Lo(Windmin) - Length(Line) - 2;
End;
GotoXY(X,Row);
Write(Borders[Border,RightConnect],Line,Borders[Border,LeftConnect]);
WindMin := WMin;
WindMax := WMax;
GotoXY(oX,oY);
End;
Procedure Title(Line : String;
TitleFormat : TitleType;
Border : BorderType);
Begin
HeaderFooter(Line,1,TitleFormat,Border);
End;
Procedure Footer(Line : String;
TitleFormat : TitleType;
Border : BorderType);
Begin
HeaderFooter(Line,Hi(WindMax)-Hi(WindMin)+3,TitleFormat,Border);
End;
Procedure FastPutVertical(Ch : Char;Count,Col,Row : Word); External;
Procedure FastPutHorizontal(Ch : Char;Count,Col,Row : Word); External;
{$L fastput.obj}
Procedure DrawVerticalLine(X,Y,Length : Word;Border : BorderType);
{ draws a vertical line with the proper connection }
{ type for interfacing with a surrounding window. }
Var
Loop : Word;
WMax : Word;
WMin : Word;
xX,xY : Integer;
Begin
WMax := WindMax;
WMin := WindMin;
xX := WhereX;
xY := WhereY;
Window(1,1,80,25);
FastPutVertical(Borders[Border,Side],Length-2,X,Succ(Y));
GotoXY(X,Y);
Write(Borders[Border,TopConnect]);
GotoXY(X,Y+Pred(Length));
Write(Borders[Border,BottomConnect]);
WindMax := WMax;
WindMin := WMin;
GotoXY(xX,xY);
End;
Procedure DrawHorizontalLine(X,Y,Length : Word;Border :BorderType);
{ draws a horizontal line with the proper connection }
{ type for interfacing with a surrounding window. }
Var
Loop : Word;
WMax : Word;
WMin : Word;
xX,xY : Integer;
Begin
WMax := WindMax;
WMin := WindMin;
xX := WhereX;
xY := WhereY;
Window(1,1,80,25);
GotoXY(X,Y);
Write(Borders[Border,LeftConnect]);
GotoXY(X+Pred(Length),Y);
Write(Borders[Border,RightConnect]);
FastPutHorizontal(Borders[Border,Top],Length-2,Succ(X),Y);
WindMax := WMax;
WindMin := WMin;
GotoXY(xX,xY);
End;
Procedure DrawBox(X1,Y1,X2,Y2,Forground,Background : Integer;Border : BorderType);
{ Draws a double box around the window and reduces the window size. }
{ Inputs are the same as for MakeWindow. }
Var
Loop : Integer;
Begin
If UseMono Then
Begin { Make sure the attributes can be }
Forground := 7; { seen on a monochrome screen. }
Background := 0;
End;
TextColor(Forground);
TextBackground(Background);
Window(1,1,80,25);
If Border = None
Then Window(X1,Y1,X2,Y2)
Else Begin
FastPutVertical(Borders[Border,Side],Y2-Y1,X1,Succ(Y1));
FastPutVertical(Borders[Border,Side],Y2-Y1,X2,Succ(Y1));
GotoXY(X1,Y1);
FastPutHorizontal(Borders[Border,Top],X2-X1,X1,Y1);{ top }
FastPutHorizontal(Borders[Border,Top],X2-X1,X1,Y2);{ bottom }
Write(Borders[Border,UpperLeft]); { upper left }
GotoXY(X2,Y1);
Write(Borders[Border,UpperRight]); { upper right }
GotoXY(X1,Y2);
Write(Borders[Border,LowerLeft]); { lower left }
FastPutHorizontal(Borders[Border,LowerRight],1,X2,Y2); { lower right }
Window(Succ(X1),Succ(Y1),Pred(X2),Pred(Y2)); { reduce the window size }
End;
ClrScr;
End;
Procedure MakeWindow(X1,Y1,X2,Y2,Forground,BackGround : Integer;
Border : BorderType);
{ Saves the screen and draws a box. }
{ Inputs are: The four window coordinates, }
{ the forground color, }
{ the background color, and }
{ the border type (see DrawBox) }
Begin
SaveScreen(X1,Y1,X2,Y2);
DrawBox(X1,Y1,X2,Y2,Forground,Background,Border);
End;
Function EGA : Boolean;
Begin
If (MemW[$C000:$001E] = $4249) And (Mem[$C000:$0020] = $4D)
Then EGA := TRUE
Else EGA := FALSE;
End;
Procedure Initialize;
Begin
UseMono := FALSE;
ScreenSaved := FALSE;
UnderScreen := Nil; { no screens saved }
DirectVideo := TRUE;
CheckSnow := TRUE;
If (VideoMode = 7) Or EGA Then CheckSnow := FALSE;
If VideoMode = 7 Then UseMono := True;
End;
Begin
Initialize;
End.